package controllers

import (
	"bytes"
	"github.com/gin-gonic/gin"
	"go.didapinche.com/foundation/ophis"
	ginstart "go.didapinche.com/gin-start"
	"go.didapinche.com/uic"
	"go.uber.org/zap"
	"time"
)

type responseBodyWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

func (r responseBodyWriter) Write(b []byte) (int, error) {
	r.body.Write(b)
	return r.ResponseWriter.Write(b)
}

// NewControllers returns a function that is use for init gin routes
func NewControllers(
	logger *zap.Logger,
	ophis *ophis.Api,
	dingDingInfoCtl *DingDingController,
	tempTypeCtl *TempTypeController,
	graphCtl *GraphPanelController,
	tempCtl *TemplateController,
	appCtl *AppController,
	accessRecordCtl *AccessRecordController,
	hookCtl *HookController,
	alertHistoryCtl *AlertHistoryController,
	alertCurrentCtl *AlertCurrentController,
	uic *uic.Api,
	apiCtl *ApiController,
	dashboardCtl *DashboardController,
) ginstart.Controllers {
	return func(r *gin.Engine) {
		{
			group := r.Group("", LogAopReq(*logger))
			{
				group.GET("/alerts", uic.AuthLogin(), alertCurrentCtl.FindAlerts)
			}
			{
				group.GET("/sla/app/stat", uic.AuthLogin(), appCtl.Find)
				// APP SLA 比较
				group.GET("/sla/app/stat/data", appCtl.StatByAppIDS)
				group.GET("/sla/metric", uic.AuthLogin(), tempCtl.FindSlaMetrics)

				//	r.GET("/api/sla", uic.AuthLogin(), apiCtl.FindApiSla)
			}
			{
				group.GET("/ding_ding_info", uic.AuthLogin(), dingDingInfoCtl.Find)
				group.DELETE("/ding_ding_info/:id", uic.AuthLogin(), dingDingInfoCtl.DeleteByID)
				group.PUT("/ding_ding_info", uic.AuthLogin(), dingDingInfoCtl.Update)
				group.POST("/ding_ding_info", uic.AuthLogin(), dingDingInfoCtl.Create)
				group.GET("/dingdings", uic.AuthLogin(), dingDingInfoCtl.FindByName)

			}
			{
				group.GET("/temp/types", uic.AuthLogin(), tempTypeCtl.FindAll)
				group.POST("/temp/type", uic.AuthLogin(), tempTypeCtl.Create)
				group.PUT("/temp/type/:id", uic.AuthLogin(), tempTypeCtl.Update)
				group.DELETE("/temp/type/:id", uic.AuthLogin(), tempTypeCtl.Delete)
			}
			{
				group.GET("/templates", uic.AuthLogin(), tempCtl.Find)
				group.POST("/template", uic.AuthPerm("echo_all"), ophis.OpenWriter(), tempCtl.Create, ophis.Record("plat-echo"))
				group.DELETE("/template/:id", uic.AuthPerm("echo_all"), ophis.OpenWriter(), tempCtl.Delete, ophis.Record("plat-echo"))
				group.PUT("/template/:id", uic.AuthPerm("echo_all"), ophis.OpenWriter(), tempCtl.Update, ophis.Record("plat-echo"))
				group.GET("/template/apps", uic.AuthLogin(), tempCtl.FindUpdateApp)
				group.GET("/template/hosts", uic.AuthLogin(), tempCtl.FindUpdateHost)
				group.GET("/template/apis", uic.AuthLogin(), tempCtl.FindUpdateApi)
				group.PUT("/template/:id/subscribe", uic.AuthLogin(), tempCtl.Subscribe)
				group.GET("/template/progress", uic.AuthLogin(), tempCtl.GetProgress)
				group.POST("/template/preview", uic.AuthLogin(), tempCtl.Preview)
				group.GET("/template/preview", uic.AuthLogin(), tempCtl.FindByKey)

			}
			{
				//r.GET("/graph_data", graphCtl.GetGraphData)
				group.POST("/hook", hookCtl.Hook)
			}
			{
				group.GET("/stat/history", uic.AuthLogin(), alertHistoryCtl.FindStatHistory)
				group.GET("/sla/group/stat", uic.AuthLogin(), appCtl.StatByGroup)

			}
			//api
			{
				//接口统计列表
				group.GET("/api/list", uic.AuthLogin(), apiCtl.FindList)
				group.GET("/api/client", uic.AuthLogin(), apiCtl.FindByZeusClient)
				group.GET("/api/sla", uic.AuthLogin(), apiCtl.FindApiSla)
				group.GET("/api/graph", uic.AuthLogin(), apiCtl.FindGraphByIsForce)
				group.GET("/api_infos/:id", uic.AuthLogin(), apiCtl.FindByID)
				group.PUT("/graphs/status", uic.AuthLogin(), apiCtl.UpdateStatus)
				//获取排行榜数据
				group.GET("/statistics", uic.AuthLogin(), apiCtl.GetStatistics)
				//获得首页各级别服务状况
				group.GET("/stat/sla", uic.AuthLogin(), apiCtl.FindSlaStat)
			}
			{
				group.GET("/app/:id/graph/type", uic.AuthLogin(), graphCtl.FindGraphByAppID)
				// 应用告警历史graph统计
				group.GET("/app/:id/alert/count", uic.AuthLogin(), alertHistoryCtl.FindAlertCountByAppId)
				// 应用当前正在告警
				group.GET("/app/:id/alert", uic.AuthLogin(), alertCurrentCtl.FindByAppID)
				group.GET("/alert/history/record", uic.AuthLogin(), alertHistoryCtl.FindAlertRecord)
				group.GET("/app/:id/alert/history", uic.AuthLogin(), alertHistoryCtl.FindAlertRecordByAppId)
				group.GET("/dashboard/:id/alert/history", uic.AuthLogin(), alertHistoryCtl.FindAlertRecordByDashboardID)
				group.GET("/api/sla_history", uic.AuthLogin(), alertHistoryCtl.FindAlertHistoryByApiId)
				group.GET("/api/sla_record", uic.AuthLogin(), alertHistoryCtl.FindAlertRecordByApiID)
			}

			{
				group.GET("/dashboards", uic.AuthLogin(), dashboardCtl.FindAll)
				group.POST("/dashboard", uic.AuthLogin(), dashboardCtl.Create)
				group.DELETE("/dashboard/:id", uic.AuthLogin(), dashboardCtl.Delete)
				group.PUT("/dashboard/:id", uic.AuthLogin(), dashboardCtl.Update)
				group.GET("/dashboard/:id/graphs", uic.AuthLogin(), graphCtl.FindByDashboardID)
				group.PUT("/graph/:graph_id/type", uic.AuthLogin(), graphCtl.UpdateGraphType)
			}
			{
				group.GET("/graph/:id", uic.AuthLogin(), graphCtl.FindByID)
				group.GET("/graphs/data", uic.AuthLogin(), graphCtl.GetGraphData)
				group.GET("/alert/history", uic.AuthLogin(), alertHistoryCtl.FindAlertRecord)

				group.GET("/alert_history", uic.AuthLogin(), alertHistoryCtl.Find)
				group.POST("/claim_alert", uic.AuthLogin(), alertHistoryCtl.Claim)
				group.POST("/graph", uic.AuthLogin(), graphCtl.Create)
				group.PUT("/graph/:graph_id", uic.AuthLogin(), graphCtl.Update)
				group.DELETE("/graph/:id", uic.AuthLogin(), graphCtl.Delete)
				group.PUT("/graph/:graph_id/position", uic.AuthLogin(), graphCtl.UpdateGraphPosition)
				group.PUT("/alert/graph/:id/subscribe", uic.AuthLogin(), uic.AuthLogin(), graphCtl.Subscribe)
				group.GET("/host/graph/type", uic.AuthLogin(), graphCtl.GetHostGraphType)
				group.PUT("/graph/:graph_id/silence", uic.AuthPerm("echo_all"), graphCtl.UpdateSilence)

			}
			{ //访问历史
				group.GET("/access/list", uic.AuthLogin(), accessRecordCtl.Find)
			}

			{
				// 修复数据
				r.GET("/app_reload", uic.AuthLogin(), appCtl.ReloadApp)

			}
			// 清理数据
			{
				r.GET("/clear_api", uic.AuthLogin(), apiCtl.ClearnApiData)
				r.GET("/clear_api_k8s", uic.AuthLogin(), graphCtl.ClearApiK8s)
				r.GET("/clear_history", uic.AuthLogin(), alertHistoryCtl.DeleteByRepeat)
			}
		}
	}
}

/**
请求之前
*/
func LogAopReq(logger zap.Logger) func(c *gin.Context) {
	return func(c *gin.Context) {
		//设置日志格式
		// 开始时间
		startTime := time.Now()
		w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer}
		c.Writer = w
		// 处理请求
		c.Next()
		// 结束时间
		endTime := time.Now()
		// 执行时间
		latencyTime := endTime.Sub(startTime)
		// 请求方式
		reqMethod := c.Request.Method
		// 请求路由
		reqUri := c.Request.RequestURI
		// 状态码
		statusCode := c.Writer.Status()
		// 请求IP
		clientIP := c.Request.Host

		logger.Info("request:",
			zap.Int("status_code", statusCode),
			zap.Duration("latency_time", latencyTime),
			zap.String("clientIP", reqMethod),
			zap.String("req_method", clientIP),
			zap.String("req_uri", reqUri))

	}
}
